package com.southminority.ethnic.service.news.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.southminority.ethnic.common.exception.BusinessException;
import com.southminority.ethnic.common.result.PageResult;
import com.southminority.ethnic.pojo.News;
import com.southminority.ethnic.mapper.news.NewsMapper;
import com.southminority.ethnic.service.news.NewsService;
import com.southminority.ethnic.controller.news.vo.NewsVO;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 新闻资讯服务实现类.
 * <p>
 * 实现了 {@link NewsService} 接口，负责处理所有与新闻资讯相关的业务逻辑。
 * 包括数据查询、转换、增删改查等操作。
 * 
 * @author SouthMinority
 */
@Service
@Transactional
public class NewsServiceImpl implements NewsService {

    private final NewsMapper newsMapper;

    public NewsServiceImpl(NewsMapper newsMapper) {
        this.newsMapper = newsMapper;
    }

    // =================================================================================
    // ==                             前端展示相关方法 (Public API)                     ==
    // =================================================================================

    @Override
    public PageResult<NewsVO> getPublishedNewsPage(Integer page, Integer size, String keyword, String category, String newsType, Long organizationId) {
        Page<News> pageObj = new Page<>(page, size);
        QueryWrapper<News> wrapper = new QueryWrapper<>();

        // 前端只查询已发布的
        wrapper.eq("status", 1);

        if (StringUtils.hasText(keyword)) {
            wrapper.and(qw -> qw.like("title", keyword).or().like("summary", keyword));
        }
        if (StringUtils.hasText(category)) {
            wrapper.eq("category", category);
        }
        if (StringUtils.hasText(newsType)) {
            wrapper.eq("news_type", newsType);
        }
        if (organizationId != null) {
            wrapper.eq("organization_id", organizationId);
        }

        // 排序规则：置顶优先，然后按发布时间倒序
        wrapper.orderByDesc("is_top").orderByDesc("publish_time");

        IPage<News> pageResult = newsMapper.selectPage(pageObj, wrapper);
        
        List<NewsVO> voList = pageResult.getRecords().stream()
                                       .map(this::convertToVO)
                                       .collect(Collectors.toList());

        return PageResult.<NewsVO>builder()
                .current(pageResult.getCurrent())
                .size(pageResult.getSize())
                .total(pageResult.getTotal())
                .pages(pageResult.getPages())
                .records(voList)
                .build();
    }

    @Override
    public NewsVO getPublishedNewsDetail(Long id) {
        News news = newsMapper.selectById(id);
        // 校验新闻是否存在且已发布
        if (news == null || news.getStatus() != 1) {
            throw new BusinessException("新闻不存在或未发布");
        }
        
        // 安全地增加浏览次数
        increaseViewCount(id);
        // 重新获取一次，确保浏览次数是最新的
        news = newsMapper.selectById(id);
        
        return convertToVO(news);
    }

    @Override
    public List<NewsVO> getTopNewsList(Integer limit) {
        QueryWrapper<News> wrapper = new QueryWrapper<>();
        wrapper.eq("status", 1)
               .eq("is_top", 1)
               .isNotNull("cover_image")
               .ne("cover_image", "")
               .orderByDesc("publish_time");
        if(limit != null && limit > 0) {
            wrapper.last("LIMIT " + limit);
        }
        
        List<News> newsList = newsMapper.selectList(wrapper);
        return newsList.stream()
                      .map(this::convertToVO)
                      .collect(Collectors.toList());
    }

    @Override
    public List<String> getNewsCategories() {
        QueryWrapper<News> wrapper = new QueryWrapper<>();
        wrapper.select("DISTINCT category")
               .eq("status", 1)
               .isNotNull("category")
               .orderByAsc("category");

        List<News> list = newsMapper.selectList(wrapper);
        return list.stream()
                .map(News::getCategory)
                .filter(StringUtils::hasText)
                .collect(Collectors.toList());
    }

    // =================================================================================
    // ==                             后台管理相关方法 (Admin API)                      ==
    // =================================================================================

    @Override
    public PageResult<NewsVO> getNewsPageForAdmin(Integer page, Integer size, String keyword, String category, String newsType, Integer status, Integer isTop) {
        Page<News> pageObj = new Page<>(page, size);
        QueryWrapper<News> wrapper = new QueryWrapper<>();

        if (StringUtils.hasText(keyword)) {
            wrapper.like("title", keyword);
        }
        if (StringUtils.hasText(category)) {
            wrapper.eq("category", category);
        }
        if (StringUtils.hasText(newsType)) {
            wrapper.eq("news_type", newsType);
        }
        if (status != null) {
            wrapper.eq("status", status);
        } else {
            // 默认不显示已删除的
            wrapper.ne("status", -1);
        }
        
        // 添加置顶状态查询条件
        if (isTop != null) {
            wrapper.eq("is_top", isTop);
        }

        wrapper.orderByDesc("is_top").orderByDesc("publish_time");

        IPage<News> pageResult = newsMapper.selectPage(pageObj, wrapper);
        
        List<NewsVO> voList = pageResult.getRecords().stream()
                                       .map(this::convertToVO)
                                       .collect(Collectors.toList());
        
        return PageResult.<NewsVO>builder()
                .current(pageResult.getCurrent())
                .size(pageResult.getSize())
                .total(pageResult.getTotal())
                .pages(pageResult.getPages())
                .records(voList)
                .build();
    }

    @Override
    public NewsVO getNewsDetailForAdmin(Long id) {
        News news = newsMapper.selectById(id);
        if (news == null) {
            throw new BusinessException("新闻不存在");
        }
        return convertToVO(news);
    }

    @Override
    public NewsVO createNews(News news) {
        if (news == null) {
            throw new BusinessException("新闻信息不能为空");
        }
        
        // 设置默认值
        if (news.getViewCount() == null) news.setViewCount(0);
        if (news.getIsTop() == null) news.setIsTop(0);
        if (news.getStatus() == null) news.setStatus(0); // 默认为草稿
        if (news.getStatus() == 1 && news.getPublishTime() == null) {
            // 如果直接发布，则设置发布时间为当前时间
            news.setPublishTime(LocalDateTime.now());
        }
        
        newsMapper.insert(news);
        return convertToVO(news);
    }

    @Override
    public NewsVO updateNews(Long id, News news) {
        News existingNews = newsMapper.selectById(id);
        if (existingNews == null) {
            throw new BusinessException("新闻不存在");
        }
        
        // 合并更新：仅对传入的非null字段进行更新，避免无意清空；字符串按需去空白
        if (news.getTitle() != null) {
            existingNews.setTitle(news.getTitle().trim());
        }
        if (news.getContent() != null) {
            existingNews.setContent(news.getContent());
        }
        if (news.getSummary() != null) {
            existingNews.setSummary(news.getSummary());
        }
        if (news.getCoverImage() != null) {
            existingNews.setCoverImage(news.getCoverImage());
        }
        if (news.getExternalUrl() != null) {
            existingNews.setExternalUrl(news.getExternalUrl().trim());
        }
        if (news.getAuthorId() != null) {
            existingNews.setAuthorId(news.getAuthorId());
        }
        if (news.getAuthorName() != null) {
            existingNews.setAuthorName(news.getAuthorName());
        }
        if (news.getCategory() != null) {
            existingNews.setCategory(news.getCategory());
        }
        if (news.getTags() != null) {
            existingNews.setTags(news.getTags());
        }
        // 新增：合并更新所属机构
        if (news.getOrganizationId() != null) {
            existingNews.setOrganizationId(news.getOrganizationId());
        }
        if (news.getIsTop() != null) {
            existingNews.setIsTop(news.getIsTop());
        }
        if (news.getPublishTime() != null) {
            existingNews.setPublishTime(news.getPublishTime());
        }
        if (news.getStatus() != null) {
            // 若从未发布→发布，补发布时间
            if (existingNews.getStatus() != 1 && news.getStatus() == 1 && existingNews.getPublishTime() == null) {
                existingNews.setPublishTime(LocalDateTime.now());
            }
            existingNews.setStatus(news.getStatus());
        }
        
        existingNews.setUpdateTime(LocalDateTime.now());
        newsMapper.updateById(existingNews);
        return convertToVO(newsMapper.selectById(id));
    }

    @Override
    public boolean deleteNews(Long id) {
        News news = newsMapper.selectById(id);
        if (news == null) {
            return true; // 幂等操作，如果已删除也返回成功
        }
        
        // 逻辑删除
        news.setStatus(-1);
        news.setUpdateTime(LocalDateTime.now());
        return newsMapper.updateById(news) > 0;
    }

    @Override
    public boolean batchDeleteNews(List<Long> ids) {
        if (ids == null || ids.isEmpty()) {
            throw new BusinessException("删除的新闻ID列表不能为空");
        }
        
        List<News> newsList = newsMapper.selectBatchIds(ids);
        if (newsList.isEmpty()) {
            return true;
        }
        
        LocalDateTime now = LocalDateTime.now();
        for (News news : newsList) {
            news.setStatus(-1);
            news.setUpdateTime(now);
            newsMapper.updateById(news);
        }
        
        return true;
    }

    @Override
    public boolean updateNewsStatus(Long id, Integer status) {
        News news = newsMapper.selectById(id);
        if (news == null) {
            throw new BusinessException("新闻不存在");
        }
        
        if (status == null || (status < -1 || status > 1)) {
            throw new BusinessException("状态值无效");
        }

        // 如果状态从非发布变为发布，且发布时间为空，则设置发布时间
        if (news.getStatus() != 1 && status == 1 && news.getPublishTime() == null) {
            news.setPublishTime(LocalDateTime.now());
        }
        
        news.setStatus(status);
        news.setUpdateTime(LocalDateTime.now());
        
        return newsMapper.updateById(news) > 0;
    }

    @Override
    public boolean setNewsTopStatus(Long id, Integer isTop) {
        News news = newsMapper.selectById(id);
        if (news == null) {
            throw new BusinessException("新闻不存在");
        }
        
        if (isTop == null || (isTop != 0 && isTop != 1)) {
            throw new BusinessException("置顶值无效");
        }
        
        news.setIsTop(isTop);
        news.setUpdateTime(LocalDateTime.now());
        
        return newsMapper.updateById(news) > 0;
    }

    // =================================================================================
    // ==                             私有辅助方法 (Private Helpers)                      ==
    // =================================================================================

    /**
     * 将 News POJO 转换为 NewsVO DTO.
     * @param news 新闻实体
     * @return 新闻VO
     */
    private NewsVO convertToVO(News news) {
        if(news == null) return null;
        NewsVO newsVO = new NewsVO();
        BeanUtils.copyProperties(news, newsVO);
        return newsVO;
    }

    /**
     * 内部方法：安全地增加一次文章浏览次数.
     * @param id 新闻ID
     */
    private void increaseViewCount(Long id) {
        News news = newsMapper.selectById(id);
        if (news != null) {
            news.setViewCount((news.getViewCount() == null ? 0 : news.getViewCount()) + 1);
            news.setUpdateTime(LocalDateTime.now());
            newsMapper.updateById(news);
        }
    }
} 
